<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#222" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#222" media="(prefers-color-scheme: dark)"><meta name="generator" content="Hexo 6.3.0">
<link rel="preconnect" href="https://fonts.googleapis.com" crossorigin>
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">

<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,300italic,400,400italic,700,700italic%7CZCOOL+QingKe+HuangYou:300,300italic,400,400italic,700,700italic%7CNoto+Sans+Simplified+Chinese:300,300italic,400,400italic,700,700italic%7CJetBrains+Mono:300,300italic,400,400italic,700,700italic&display=swap&subset=latin,latin-ext">

<link rel="stylesheet" href="/lib/@fortawesome/fontawesome-free/css/all.min.css" integrity="sha256-HtsXJanqjKTc8vVQjO4YMhiqFoXkfBsjBWcX91T1jr8=" crossorigin="anonymous">
  <link rel="stylesheet" href="/lib/animate.css/animate.min.css" integrity="sha256-PR7ttpcvz8qrF57fur/yAx1qXMFJeJFiA6pSzWi0OIE=" crossorigin="anonymous">
  <link rel="stylesheet" href="/lib/@fancyapps/ui/dist/fancybox/fancybox.css" integrity="sha256-RvRHGSuWAxZpXKV9lLDt2e+rZ+btzn48Wp4ueS3NZKs=" crossorigin="anonymous">

<script class="next-config" data-name="main" type="application/json">{"hostname":"wyatex.online","root":"/","images":"/images","scheme":"Pisces","darkmode":true,"version":"8.18.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12},"copycode":{"enable":true,"style":"mac"},"fold":{"enable":false,"height":500},"bookmark":{"enable":false,"color":"#222","save":"auto"},"mediumzoom":false,"lazyload":true,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"stickytabs":false,"motion":{"enable":true,"async":true,"transition":{"menu_item":"fadeInDown","post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果：${query}","hits_time":"找到 ${hits} 个搜索结果（用时 ${time} 毫秒）","hits":"找到 ${hits} 个搜索结果"},"path":"/search.xml","localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":true}}</script><script src="/js/config.js"></script>

    <meta name="description" content="新系列开坑">
<meta property="og:type" content="article">
<meta property="og:title" content="ts笔记（1）：搭建和一些基础类型">
<meta property="og:url" content="https://wyatex.online/TypeScript/ts%E7%AC%94%E8%AE%B0%EF%BC%881%EF%BC%89%EF%BC%9A%E6%90%AD%E5%BB%BA%E5%92%8C%E4%B8%80%E4%BA%9B%E5%9F%BA%E7%A1%80%E7%B1%BB%E5%9E%8B/index.html">
<meta property="og:site_name" content="Wyatex&#96;s blog">
<meta property="og:description" content="新系列开坑">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2021-10-28T11:15:18.000Z">
<meta property="article:modified_time" content="2023-05-05T01:25:47.303Z">
<meta property="article:author" content="Wyatex">
<meta property="article:tag" content="前端">
<meta property="article:tag" content="学习笔记">
<meta property="article:tag" content="TypeScript">
<meta name="twitter:card" content="summary">


<link rel="canonical" href="https://wyatex.online/TypeScript/ts%E7%AC%94%E8%AE%B0%EF%BC%881%EF%BC%89%EF%BC%9A%E6%90%AD%E5%BB%BA%E5%92%8C%E4%B8%80%E4%BA%9B%E5%9F%BA%E7%A1%80%E7%B1%BB%E5%9E%8B/">



<script class="next-config" data-name="page" type="application/json">{"sidebar":"","isHome":false,"isPost":true,"lang":"zh-CN","comments":true,"permalink":"https://wyatex.online/TypeScript/ts%E7%AC%94%E8%AE%B0%EF%BC%881%EF%BC%89%EF%BC%9A%E6%90%AD%E5%BB%BA%E5%92%8C%E4%B8%80%E4%BA%9B%E5%9F%BA%E7%A1%80%E7%B1%BB%E5%9E%8B/","path":"TypeScript/ts笔记（1）：搭建和一些基础类型/","title":"ts笔记（1）：搭建和一些基础类型"}</script>

<script class="next-config" data-name="calendar" type="application/json">""</script>
<title>ts笔记（1）：搭建和一些基础类型 | Wyatex`s blog</title>
  








  <noscript>
    <link rel="stylesheet" href="/css/noscript.css">
  </noscript>
</head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <div class="column">
      <header class="header" itemscope itemtype="http://schema.org/WPHeader"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏" role="button">
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <i class="logo-line"></i>
      <p class="site-title">Wyatex`s blog</p>
      <i class="logo-line"></i>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger" aria-label="搜索" role="button">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>



<nav class="site-nav">
  <ul class="main-menu menu"><li class="menu-item menu-item-home"><a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a></li><li class="menu-item menu-item-about"><a href="/about/" rel="section"><i class="fa fa-user fa-fw"></i>关于</a></li><li class="menu-item menu-item-tags"><a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签<span class="badge">97</span></a></li><li class="menu-item menu-item-categories"><a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类<span class="badge">26</span></a></li><li class="menu-item menu-item-archives"><a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档<span class="badge">155</span></a></li><li class="menu-item menu-item-编程"><a href="/programming/" rel="section"><i class="fa fa-book fa-fw"></i>编程</a></li><li class="menu-item menu-item-蹲坑读物"><a href="/%E5%B9%B2%E8%B4%A7/%E5%BC%80%E5%8F%91%E4%BA%A4%E6%B5%81%E7%BE%A4%E5%88%86%E4%BA%AB%E8%AE%B0%E5%BD%95/" rel="section"><i class="fa fa-book fa-fw"></i>蹲坑读物</a></li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup"><div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off" maxlength="80"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close" role="button">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div class="search-result-container no-result">
  <div class="search-result-icon">
    <i class="fa fa-spinner fa-pulse fa-5x"></i>
  </div>
</div>

    </div>
  </div>

</header>
        
  
  <aside class="sidebar">

    <div class="sidebar-inner sidebar-nav-active sidebar-toc-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
            <div class="post-toc animated"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#%E6%90%AD%E5%BB%BA"><span class="nav-number">1.</span> <span class="nav-text">搭建</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#Playground"><span class="nav-number">1.1.</span> <span class="nav-text">Playground</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%AE%89%E8%A3%85-TypeScript"><span class="nav-number">1.2.</span> <span class="nav-text">安装 TypeScript</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#HelloWorld"><span class="nav-number">1.3.</span> <span class="nav-text">HelloWorld</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%9F%BA%E6%9C%AC%E8%AF%AD%E6%B3%95"><span class="nav-number">2.</span> <span class="nav-text">基本语法</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%8E%9F%E5%A7%8B%E7%B1%BB%E5%9E%8B"><span class="nav-number">2.1.</span> <span class="nav-text">原始类型</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AD%97%E7%AC%A6%E4%B8%B2"><span class="nav-number">2.1.1.</span> <span class="nav-text">字符串</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%95%B0%E5%AD%97"><span class="nav-number">2.1.2.</span> <span class="nav-text">数字</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%B8%83%E5%B0%94%E5%80%BC"><span class="nav-number">2.1.3.</span> <span class="nav-text">布尔值</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Symbol"><span class="nav-number">2.1.4.</span> <span class="nav-text">Symbol</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%B1%BB%E5%9E%8B%E6%8E%A8%E5%AF%BC"><span class="nav-number">2.2.</span> <span class="nav-text">类型推导</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%A4%8D%E6%9D%82%E5%9F%BA%E7%A1%80%E7%B1%BB%E5%9E%8B"><span class="nav-number">3.</span> <span class="nav-text">复杂基础类型</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%95%B0%E7%BB%84"><span class="nav-number">3.1.</span> <span class="nav-text">数组</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%89%B9%E6%AE%8A%E7%B1%BB%E5%9E%8B"><span class="nav-number">3.2.</span> <span class="nav-text">特殊类型</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#any"><span class="nav-number">3.2.1.</span> <span class="nav-text">any</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#unknown"><span class="nav-number">3.2.2.</span> <span class="nav-text">unknown</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#void%E3%80%81undefined%E3%80%81null"><span class="nav-number">3.2.3.</span> <span class="nav-text">void、undefined、null</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#never"><span class="nav-number">3.2.4.</span> <span class="nav-text">never</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#object"><span class="nav-number">3.2.5.</span> <span class="nav-text">object</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E7%B1%BB%E5%9E%8B%E6%96%AD%E8%A8%80%EF%BC%88Type-Assertion%EF%BC%89"><span class="nav-number">4.</span> <span class="nav-text">类型断言（Type Assertion）</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E7%B1%BB%E5%9E%8B%E6%8E%A8%E6%96%AD"><span class="nav-number">5.</span> <span class="nav-text">类型推断</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%B8%8A%E4%B8%8B%E6%96%87%E6%8E%A8%E6%96%AD"><span class="nav-number">5.1.</span> <span class="nav-text">上下文推断</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%AD%97%E9%9D%A2%E9%87%8F%E7%B1%BB%E5%9E%8B"><span class="nav-number">6.</span> <span class="nav-text">字面量类型</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%AD%97%E9%9D%A2%E9%87%8F%E7%B1%BB%E5%9E%8B"><span class="nav-number">6.1.</span> <span class="nav-text">字符串字面量类型</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Literal-Widening-%E5%AD%97%E9%9D%A2%E9%87%8F%E7%B1%BB%E5%9E%8B%E6%8B%93%E5%AE%BD"><span class="nav-number">6.2.</span> <span class="nav-text">Literal Widening &#x2F; 字面量类型拓宽</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Type-Widening-%E7%B1%BB%E5%9E%8B%E6%8B%93%E5%AE%BD"><span class="nav-number">6.3.</span> <span class="nav-text">Type Widening &#x2F; 类型拓宽</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Type-Narrowing-%E7%B1%BB%E5%9E%8B%E7%BC%A9%E5%B0%8F"><span class="nav-number">6.4.</span> <span class="nav-text">Type Narrowing &#x2F; 类型缩小</span></a></li></ol></li></ol></div>
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-author animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="Wyatex"
      src="/images/avatar.jpg">
  <p class="site-author-name" itemprop="name">Wyatex</p>
  <div class="site-description" itemprop="description">这里是我用来做笔记的网站哟~</div>
</div>
<div class="site-state-wrap animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
        <a href="/archives/">
          <span class="site-state-item-count">155</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
          <a href="/categories/">
        <span class="site-state-item-count">26</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
          <a href="/tags/">
        <span class="site-state-item-count">97</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author animated">
      <span class="links-of-author-item">
        <a href="https://github.com/wyatex" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;wyatex" rel="noopener me" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="mailto:wyatex@qq.com" title="E-Mail → mailto:wyatex@qq.com" rel="noopener me" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
  </div>

        </div>
      </div>
    </div>

    
    <div class="sidebar-inner sidebar-blogroll">
      <div class="links-of-blogroll animated">
        <div class="links-of-blogroll-title"><i class="fa fa-globe fa-fw"></i>
          链接
        </div>
        <ul class="links-of-blogroll-list">
            <li class="links-of-blogroll-item">
              <a href="https://antfu.me/" title="https:&#x2F;&#x2F;antfu.me&#x2F;" rel="noopener" target="_blank">Anthony Fu</a>
            </li>
            <li class="links-of-blogroll-item">
              <a href="https://www.codesky.me/" title="https:&#x2F;&#x2F;www.codesky.me&#x2F;" rel="noopener" target="_blank">CodeSky</a>
            </li>
            <li class="links-of-blogroll-item">
              <a href="https://learn.lianglianglee.com/" title="https:&#x2F;&#x2F;learn.lianglianglee.com&#x2F;" rel="noopener" target="_blank">技术文章摘抄</a>
            </li>
        </ul>
      </div>
    </div>
        <div class="pjax">
        <div class="sidebar-inner sidebar-post-related">
          <div class="animated">
              <div class="links-of-blogroll-title"><i class="fa fa-signs-post fa-fw"></i>
    相关文章
  </div>
  <ul class="popular-posts">
    <li class="popular-posts-item">
      <a class="popular-posts-link" href="/TypeScript/ts%E7%AC%94%E8%AE%B0%EF%BC%886%EF%BC%89%EF%BC%9A%E4%BD%BF%E7%94%A8TypeScript%E5%BC%80%E5%8F%91Node.js%E5%BA%94%E7%94%A8/" rel="bookmark">
        <time class="popular-posts-time">2021-11-15</time>
        <br>
      ts笔记（6）：常见TypeScript错误、开发Node.js应用
      </a>
    </li>
    <li class="popular-posts-item">
      <a class="popular-posts-link" href="/TypeScript/ts%E7%AC%94%E8%AE%B0%EF%BC%882%EF%BC%89%EF%BC%9A%E5%87%BD%E6%95%B0%E3%80%81%E7%B1%BB%E3%80%81%E6%8E%A5%E5%8F%A3%E7%B1%BB%E5%9E%8B%E5%92%8C%E7%B1%BB%E5%9E%8B%E5%88%AB%E5%90%8D/" rel="bookmark">
        <time class="popular-posts-time">2021-10-31</time>
        <br>
      ts笔记（2）：函数、类、接口类型和类型别名
      </a>
    </li>
    <li class="popular-posts-item">
      <a class="popular-posts-link" href="/TypeScript/ts%E7%AC%94%E8%AE%B0%EF%BC%883%EF%BC%89%EF%BC%9A%E8%81%94%E5%90%88%E7%B1%BB%E5%9E%8B%E3%80%81%E4%BA%A4%E5%8F%89%E7%B1%BB%E5%9E%8B%E3%80%81%E6%9E%9A%E4%B8%BE%E7%B1%BB%E5%9E%8B%E3%80%81%E6%B3%9B%E5%9E%8B/" rel="bookmark">
        <time class="popular-posts-time">2021-11-02</time>
        <br>
      ts笔记（3）：联合类型、交叉类型、枚举类型、泛型
      </a>
    </li>
    <li class="popular-posts-item">
      <a class="popular-posts-link" href="/TypeScript/ts%E7%AC%94%E8%AE%B0%EF%BC%884%EF%BC%89%EF%BC%9A%E7%B1%BB%E5%9E%8B%E5%AE%88%E5%8D%AB%E3%80%81%E7%B1%BB%E5%9E%8B%E5%85%BC%E5%AE%B9%E3%80%81%E5%A2%9E%E5%BC%BA%E7%B1%BB%E5%9E%8B%E7%B3%BB%E7%BB%9F/" rel="bookmark">
        <time class="popular-posts-time">2021-11-06</time>
        <br>
      ts笔记（4）：类型守卫、类型兼容、增强类型系统
      </a>
    </li>
    <li class="popular-posts-item">
      <a class="popular-posts-link" href="/TypeScript/ts%E9%BB%91%E9%AD%94%E6%B3%95%E6%95%99%E5%AD%A6%EF%BC%881%EF%BC%89%EF%BC%9A%E5%89%8D%E7%BD%AE%E7%9F%A5%E8%AF%86/" rel="bookmark">
        <time class="popular-posts-time">2023-04-20</time>
        <br>
      TypeScript黑魔法教学（1）：前置知识
      </a>
    </li>
  </ul>

          </div>
        </div>
        </div>
  </aside>


    </div>

    <div class="main-inner post posts-expand">


  


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://wyatex.online/TypeScript/ts%E7%AC%94%E8%AE%B0%EF%BC%881%EF%BC%89%EF%BC%9A%E6%90%AD%E5%BB%BA%E5%92%8C%E4%B8%80%E4%BA%9B%E5%9F%BA%E7%A1%80%E7%B1%BB%E5%9E%8B/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.jpg">
      <meta itemprop="name" content="Wyatex">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Wyatex`s blog">
      <meta itemprop="description" content="这里是我用来做笔记的网站哟~">
    </span>

    <span hidden itemprop="post" itemscope itemtype="http://schema.org/CreativeWork">
      <meta itemprop="name" content="ts笔记（1）：搭建和一些基础类型 | Wyatex`s blog">
      <meta itemprop="description" content="">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          ts笔记（1）：搭建和一些基础类型
        </h1>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2021-10-28 19:15:18" itemprop="dateCreated datePublished" datetime="2021-10-28T19:15:18+08:00">2021-10-28</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar-check"></i>
      </span>
      <span class="post-meta-item-text">更新于</span>
      <time title="修改时间：2023-05-05 09:25:47" itemprop="dateModified" datetime="2023-05-05T09:25:47+08:00">2023-05-05</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/TypeScript/" itemprop="url" rel="index"><span itemprop="name">TypeScript</span></a>
        </span>
    </span>

  
    <span class="post-meta-item" title="阅读次数" id="busuanzi_container_page_pv">
      <span class="post-meta-item-icon">
        <i class="far fa-eye"></i>
      </span>
      <span class="post-meta-item-text">阅读次数：</span>
      <span id="busuanzi_value_page_pv"></span>
    </span>
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody"><p>新系列开坑</p>
<span id="more"></span>

<h1 id="搭建"><a href="#搭建" class="headerlink" title="搭建"></a>搭建</h1><h2 id="Playground"><a href="#Playground" class="headerlink" title="Playground"></a>Playground</h2><p>不需要安装，可以直接运行，<a target="_blank" rel="noopener" href="https://www.typescriptlang.org/zh/play">官方中文版</a>、<a target="_blank" rel="noopener" href="https://www.typescriptlang.org/play">官方英文版</a></p>
<h2 id="安装-TypeScript"><a href="#安装-TypeScript" class="headerlink" title="安装 TypeScript"></a>安装 TypeScript</h2><p>使用 npm 或者 yarn 进行安装</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">npm i -g typescript</span><br><span class="line">// 或者</span><br><span class="line">yarn add -g typescript</span><br></pre></td></tr></table></figure>

<p>安装完成后查看版本：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tsc -v</span><br></pre></td></tr></table></figure>

<h2 id="HelloWorld"><a href="#HelloWorld" class="headerlink" title="HelloWorld"></a>HelloWorld</h2><p>使用 <code>tsc --init</code> 命令在当前目录创建一个 <code>tsconfig.json</code> 文件。<br>为了学习，在配置文件里修改成如下：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="string">&quot;compilerOptions&quot;</span>: &#123;</span><br><span class="line">    <span class="comment">/* Strict Type-Checking Options */</span></span><br><span class="line">    <span class="string">&quot;strict&quot;</span>: <span class="literal">true</span>,                           <span class="comment">/* Enable all strict type-checking options. */</span></span><br><span class="line">    <span class="string">&quot;noImplicitAny&quot;</span>: <span class="literal">true</span>,                 <span class="comment">/* Raise error on expressions and declarations with an implied &#x27;any&#x27; type. */</span></span><br><span class="line">    <span class="string">&quot;strictNullChecks&quot;</span>: <span class="literal">true</span>,              <span class="comment">/* Enable strict null checks. */</span></span><br><span class="line">    <span class="string">&quot;strictFunctionTypes&quot;</span>: <span class="literal">true</span>,           <span class="comment">/* Enable strict checking of function types. */</span></span><br><span class="line">    <span class="string">&quot;strictBindCallApply&quot;</span>: <span class="literal">true</span>,           <span class="comment">/* Enable strict &#x27;bind&#x27;, &#x27;call&#x27;, and &#x27;apply&#x27; methods on functions. */</span></span><br><span class="line">    <span class="string">&quot;strictPropertyInitialization&quot;</span>: <span class="literal">true</span>,  <span class="comment">/* Enable strict checking of property initialization in classes. */</span></span><br><span class="line">    <span class="string">&quot;noImplicitThis&quot;</span>: <span class="literal">true</span>,                <span class="comment">/* Raise error on &#x27;this&#x27; expressions with an implied &#x27;any&#x27; type. */</span></span><br><span class="line">    <span class="string">&quot;alwaysStrict&quot;</span>: <span class="literal">false</span>,                  <span class="comment">/* Parse in strict mode and emit &quot;use strict&quot; for each source file. */</span></span><br><span class="line"></span><br><span class="line">    <span class="string">&quot;target&quot;</span>: <span class="string">&quot;esnext&quot;</span>,                          <span class="comment">/* Specify ECMAScript target version: &#x27;ES3&#x27; (default), &#x27;ES5&#x27;, &#x27;ES2015&#x27;, &#x27;ES2016&#x27;, &#x27;ES2017&#x27;, &#x27;ES2018&#x27;, &#x27;ES2019&#x27;, &#x27;ES2020&#x27;, or &#x27;ESNEXT&#x27;. */</span></span><br><span class="line">    <span class="string">&quot;module&quot;</span>: <span class="string">&quot;esnext&quot;</span>,                     <span class="comment">/* Specify module code generation: &#x27;none&#x27;, &#x27;commonjs&#x27;, &#x27;amd&#x27;, &#x27;system&#x27;, &#x27;umd&#x27;, &#x27;es2015&#x27;, &#x27;es2020&#x27;, or &#x27;ESNext&#x27;. */</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>新建一个 HelloWorld.ts 文件：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">say</span>(<span class="params">word: <span class="built_in">string</span></span>) &#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(word)</span><br><span class="line">&#125;</span><br><span class="line"><span class="title function_">say</span>(<span class="string">&#x27;Hello, World&#x27;</span>)</span><br></pre></td></tr></table></figure>

<p>在该目录执行 tsc 命令，HelloWorld.ts 会编译出一个 HelloWorld.js 文件。</p>
<blockquote>
<p>注意：指定转译的目标文件后，tsc 将忽略当前应用路径下的 tsconfig.json 配置，因此我们需要通过显式设定如下所示的参数，让 tsc 以严格模式检测并转译 TypeScript 代码。</p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tsc HelloWorld.ts --strict --alwaysStrict false</span><br></pre></td></tr></table></figure>

<p>同时，我们可以给 tsc 设定一个 watch 参数监听文件内容变更，实时进行类型检测和代码转译，如下代码所示：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tsc HelloWorld.ts --strict --alwaysStrict false --watch</span><br></pre></td></tr></table></figure>

<p>也可以直接使用 ts-node 运行 HelloWorld.ts：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">npm i -g ts-node</span><br><span class="line">// or</span><br><span class="line">yarn add -g ts-node</span><br><span class="line"></span><br><span class="line">ts-node HelloWorld.ts // 输出：Hello, World</span><br></pre></td></tr></table></figure>

<p>在编辑器比如 vscode 将 <code>&#39;Hello, World&#39;</code> 改成 1 即可看到 vscode 立刻作出提示：<code>error TS2345: Argument of type &#39;number&#39; is not assignable to parameter of type &#39;string&#39;.</code>，这就是类型检查带来的好处。</p>
<h1 id="基本语法"><a href="#基本语法" class="headerlink" title="基本语法"></a>基本语法</h1><p>在语法层面，缺省类型注解的 TypeScript 与 JavaScript 完全一致。比如：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> num = <span class="number">1</span></span><br></pre></td></tr></table></figure>

<p>示例中的语法同时符合 JavaScript 语法和 TypeScript 语法。而在 ts 中可以加上类型标注：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="attr">num</span>: <span class="built_in">number</span> = <span class="number">1</span></span><br></pre></td></tr></table></figure>

<blockquote>
<p><code>number</code> 表示数字类型，<code>:</code> 用来分割变量和类型的分隔符。</p>
</blockquote>
<p>同理，我们也可以把:后的 number 换成其他的类型（比如 JavaScript 原始类型：number、string、boolean、null、undefined、symbol 等）</p>
<h2 id="原始类型"><a href="#原始类型" class="headerlink" title="原始类型"></a>原始类型</h2><p>在 JavaScript 中，原始类型指的是非对象且没有方法的数据类型，它包括 string、number、bigint、boolean、undefined 和 symbol 这六种 （null 是一个伪原始类型，它在 JavaScript 中实际上是一个对象，且所有的结构化类型都是通过 null 原型链派生而来）。</p>
<h3 id="字符串"><a href="#字符串" class="headerlink" title="字符串"></a>字符串</h3><p>在 JavaScript 中，我们可以使用 string 表示 JavaScript 中任意的字符串（包括模板字符串），ts 也是类似：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="attr">firstname</span>: <span class="built_in">string</span> = <span class="string">&#x27;Captain&#x27;</span> <span class="comment">// 字符串字面量</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">familyname</span>: <span class="built_in">string</span> = <span class="title class_">String</span>(<span class="string">&#x27;S&#x27;</span>) <span class="comment">// 显式类型转换</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">fullname</span>: <span class="built_in">string</span> = <span class="string">`my name is <span class="subst">$&#123;firstname&#125;</span>.<span class="subst">$&#123;familyname&#125;</span>`</span> <span class="comment">// 模板字符串</span></span><br></pre></td></tr></table></figure>

<p>所有 JavaScript 支持的定义字符串的方法，我们都可以直接在 TypeScript 中使用。</p>
<h3 id="数字"><a href="#数字" class="headerlink" title="数字"></a>数字</h3><p>同样，可以使用 number 类型表示 JavaScript 已经支持或者即将支持的十进制整数、浮点数，以及二进制数、八进制数、十六进制数，如下：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/** 十进制整数 */</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">integer</span>: <span class="built_in">number</span> = <span class="number">6</span></span><br><span class="line"><span class="comment">/** 十进制整数 */</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">integer2</span>: <span class="built_in">number</span> = <span class="title class_">Number</span>(<span class="number">42</span>)</span><br><span class="line"><span class="comment">/** 十进制浮点数 */</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">decimal</span>: <span class="built_in">number</span> = <span class="number">3.14</span></span><br><span class="line"><span class="comment">/** 二进制整数 */</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">binary</span>: <span class="built_in">number</span> = <span class="number">0b1010</span></span><br><span class="line"><span class="comment">/** 八进制整数 */</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">octal</span>: <span class="built_in">number</span> = <span class="number">0o744</span></span><br><span class="line"><span class="comment">/** 十六进制整数 */</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">hex</span>: <span class="built_in">number</span> = <span class="number">0xf00d</span></span><br></pre></td></tr></table></figure>

<p>如果使用较少的大整数，那么我们可以使用 bigint 类型来表示，如下代码所示。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="attr">big</span>: <span class="built_in">bigint</span> = <span class="number">100n</span></span><br></pre></td></tr></table></figure>

<h3 id="布尔值"><a href="#布尔值" class="headerlink" title="布尔值"></a>布尔值</h3><p>还是和 js 差不多</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/** TypeScript 真香 为 真 */</span></span><br><span class="line"><span class="keyword">let</span> <span class="title class_">TypeScriptIsGreat</span>: <span class="built_in">boolean</span> = <span class="literal">true</span></span><br><span class="line"><span class="comment">/** TypeScript 太糟糕了 为 否 */</span></span><br><span class="line"><span class="keyword">let</span> <span class="title class_">TypeScriptIsBad</span>: <span class="built_in">boolean</span> = <span class="literal">false</span></span><br></pre></td></tr></table></figure>

<h3 id="Symbol"><a href="#Symbol" class="headerlink" title="Symbol"></a>Symbol</h3><p>自 ECMAScript 6 起，TypeScript 开始支持新的 Symbol 原始类型， 即我们可以通过 Symbol 构造函数，创建一个独一无二的标记</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="attr">sym1</span>: <span class="built_in">symbol</span> = <span class="title class_">Symbol</span>()</span><br><span class="line"><span class="keyword">let</span> <span class="attr">sym2</span>: <span class="built_in">symbol</span> = <span class="title class_">Symbol</span>(<span class="string">&#x27;42&#x27;</span>)</span><br></pre></td></tr></table></figure>

<blockquote>
<p>TypeScript 还包含 Number、String、Boolean、Symbol 等类型（注意区分大小写），和小写格式对应的 number、string、boolean、symbol 并不一样。</p>
</blockquote>
<h2 id="类型推导"><a href="#类型推导" class="headerlink" title="类型推导"></a>类型推导</h2><p>在变量声明的同时进行定义，ts 可以为我们进行类型推导：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> num = <span class="number">1</span></span><br><span class="line"><span class="comment">// 等价于</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">num</span>: <span class="built_in">number</span> = <span class="number">1</span></span><br><span class="line"></span><br><span class="line">num = <span class="string">&#x27;Hello&#x27;</span> <span class="comment">// 报错：TS2322: Type &#x27;string&#x27; is not assignable to type &#x27;number&#x27;.</span></span><br></pre></td></tr></table></figure>

<h1 id="复杂基础类型"><a href="#复杂基础类型" class="headerlink" title="复杂基础类型"></a>复杂基础类型</h1><h2 id="数组"><a href="#数组" class="headerlink" title="数组"></a>数组</h2><p>因为 TypeScript 的数组和元组转译为 JavaScript 后都是数组，所以这里我们把数组和元组这两个类型整合到一起介绍。</p>
<p>数组类型（Array）：在 TypeScript 中，我们也可以像 JavaScript 一样定义数组类型，并且指定数组元素的类型</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/** 子元素是数字类型的数组 */</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">arrayOfNumber</span>: <span class="built_in">number</span>[] = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]</span><br><span class="line"><span class="comment">/** 子元素是字符串类型的数组 */</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">arrayOfString</span>: <span class="built_in">string</span>[] = [<span class="string">&#x27;x&#x27;</span>, <span class="string">&#x27;y&#x27;</span>, <span class="string">&#x27;z&#x27;</span>]</span><br></pre></td></tr></table></figure>

<p>同样，我们也可以使用 Array 泛型定义数组类型:</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/** 子元素是数字类型的数组 */</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">arrayOfNumber</span>: <span class="title class_">Array</span>&lt;<span class="built_in">number</span>&gt; = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]</span><br><span class="line"><span class="comment">/** 子元素是字符串类型的数组 */</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">arrayOfString</span>: <span class="title class_">Array</span>&lt;<span class="built_in">string</span>&gt; = [<span class="string">&#x27;x&#x27;</span>, <span class="string">&#x27;y&#x27;</span>, <span class="string">&#x27;z&#x27;</span>]</span><br></pre></td></tr></table></figure>

<blockquote>
<p>这里更推荐使用<code>[]</code>的方式</p>
</blockquote>
<p>元组类型（Tuple）：元组最重要的特性是可以限制数组元素的个数和类型，它特别适合用来实现多值返回。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="attr">myTuple</span>: [<span class="built_in">number</span>, <span class="built_in">string</span>] = [<span class="number">1</span>, <span class="string">&#x27;hello&#x27;</span>]</span><br><span class="line"></span><br><span class="line"><span class="comment">// 如果不使用类型标注的话，会变成另外一种类型</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> myTuple1 = [<span class="number">1</span>, <span class="string">&#x27;hello&#x27;</span>]</span><br><span class="line"><span class="comment">// 等价于 let myTuple: (string | number)[]</span></span><br></pre></td></tr></table></figure>

<h2 id="特殊类型"><a href="#特殊类型" class="headerlink" title="特殊类型"></a>特殊类型</h2><h3 id="any"><a href="#any" class="headerlink" title="any"></a>any</h3><p>在使用 any 之前要知道，<strong>Any is Hell（Any 是地狱）</strong>，它会使类型检查失效。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="attr">anything</span>: <span class="built_in">any</span> = <span class="number">1</span></span><br><span class="line">anything.<span class="title function_">doAnything</span>() <span class="comment">//不会提示错误</span></span><br><span class="line">anything = <span class="string">&#x27;hello&#x27;</span> <span class="comment">//不会提示错误</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">num</span>: <span class="built_in">number</span> = anything <span class="comment">//不会提示错误</span></span><br></pre></td></tr></table></figure>

<p>从长远来看，使用 any 绝对是一个坏习惯。如果一个 TypeScript 应用中充满了 any，此时静态类型检测基本起不到任何作用，也就是说与直接使用 JavaScript 没有任何区别。</p>
<h3 id="unknown"><a href="#unknown" class="headerlink" title="unknown"></a>unknown</h3><p>unknown 是 TypeScript 3.0 中添加的一个类型，它主要用来描述类型并不确定的变量，它可以接收多种返回值，但是它只能赋值给 unknown 和 any。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="attr">result</span>: <span class="built_in">unknown</span></span><br><span class="line"><span class="keyword">if</span> (x) &#123;</span><br><span class="line">  result = <span class="title function_">x</span>()</span><br><span class="line">&#125; <span class="keyword">else</span> <span class="keyword">if</span> (y) &#123;</span><br><span class="line">  result = <span class="title function_">y</span>()</span><br><span class="line">&#125; <span class="comment">// ...</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> <span class="attr">result</span>: <span class="built_in">unknown</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">num</span>: <span class="built_in">number</span> = result <span class="comment">// 提示 ts(2322)</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">anything</span>: <span class="built_in">any</span> = result <span class="comment">// 不会提示错误</span></span><br></pre></td></tr></table></figure>

<p>使用 unknown 后，TypeScript 会对它做类型检测。但是，如果不缩小类型（Type Narrowing），我们对 unknown 执行的任何操作都会出现如下所示错误：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="attr">result</span>: <span class="built_in">unknown</span></span><br><span class="line">result.<span class="title function_">toFixed</span>() <span class="comment">// 提示 ts(2571)</span></span><br></pre></td></tr></table></figure>

<p>而所有的类型缩小手段对 unknown 都有效</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="attr">result</span>: <span class="built_in">unknown</span></span><br><span class="line"><span class="keyword">if</span> (<span class="keyword">typeof</span> result === <span class="string">&#x27;number&#x27;</span>) &#123;</span><br><span class="line">  result.<span class="title function_">toFixed</span>() <span class="comment">// 此处 hover result 提示类型是 number，不会提示错误</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="void、undefined、null"><a href="#void、undefined、null" class="headerlink" title="void、undefined、null"></a>void、undefined、null</h3><p><strong>void 类型</strong>：它仅适用于表示没有返回值的函数。即如果该函数没有返回值，那它的类型就是 void。</p>
<p>undefined 和 void 是 ts 中值于类型同名的例外。但是在 ts 中实际上并没有啥作用。undefined 的最大价值主要体现在接口类型上，它表示一个可缺省、未定义的属性。</p>
<blockquote>
<p>我们可以把 undefined 值或类型是 undefined 的变量赋值给 void 类型变量，反过来，类型是 void 但值是 undefined 的变量不能赋值给 undefined 类型。</p>
</blockquote>
<p>不建议随意使用非空断言来排除值可能为 null 或 undefined 的情况，因为这样很不安全：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">userInfo.<span class="property">id</span>!.<span class="title function_">toFixed</span>() <span class="comment">// ok，但不建议</span></span><br><span class="line">userInfo.<span class="property">name</span>!.<span class="title function_">toLowerCase</span>() <span class="comment">// ok，但不建议</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 推荐做法</span></span><br><span class="line">userInfo.<span class="property">id</span>?.<span class="title function_">toFixed</span>() <span class="comment">// Optional Chain</span></span><br><span class="line"><span class="keyword">const</span> myName = userInfo.<span class="property">name</span> ?? <span class="string">`my name is <span class="subst">$&#123;info.name&#125;</span>`</span> <span class="comment">// 空值合并</span></span><br></pre></td></tr></table></figure>

<h3 id="never"><a href="#never" class="headerlink" title="never"></a>never</h3><p>never 表示永远不会发生值的类型。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">ThrowError</span>(<span class="params">msg: <span class="built_in">string</span></span>): <span class="built_in">never</span> &#123;</span><br><span class="line">  <span class="keyword">throw</span> <span class="title class_">Error</span>(msg)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">InfiniteLoop</span>(<span class="params"></span>): <span class="built_in">never</span> &#123;</span><br><span class="line">  <span class="keyword">while</span> (<span class="literal">true</span>) &#123;&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>never 是所有类型的子类型，它可以给所有类型赋值:</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="title class_">Unreachable</span>: <span class="built_in">never</span> = <span class="number">1</span> <span class="comment">// ts(2322)</span></span><br><span class="line"><span class="title class_">Unreachable</span> = <span class="string">&#x27;string&#x27;</span> <span class="comment">// ts(2322)</span></span><br><span class="line"><span class="title class_">Unreachable</span> = <span class="literal">true</span> <span class="comment">// ts(2322)</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">num</span>: <span class="built_in">number</span> = <span class="title class_">Unreachable</span> <span class="comment">// ok</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">str</span>: <span class="built_in">string</span> = <span class="title class_">Unreachable</span> <span class="comment">// ok</span></span><br><span class="line"><span class="keyword">let</span> <span class="attr">bool</span>: <span class="built_in">boolean</span> = <span class="title class_">Unreachable</span> <span class="comment">// ok</span></span><br></pre></td></tr></table></figure>

<h3 id="object"><a href="#object" class="headerlink" title="object"></a>object</h3><p>object 类型表示非原始类型的类型，即非  number、string、boolean、bigint、symbol、null、undefined 的类型。然而这个类型并没有什么作用，用起来会有种 any 的感觉。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">declare</span> <span class="keyword">function</span> <span class="title function_">create</span>(<span class="params">o: <span class="built_in">object</span> | <span class="literal">null</span></span>): <span class="built_in">any</span></span><br><span class="line"><span class="title function_">create</span>(&#123;&#125;) <span class="comment">// ok</span></span><br><span class="line"><span class="title function_">create</span>(<span class="function">() =&gt;</span> <span class="literal">null</span>) <span class="comment">// ok</span></span><br><span class="line"><span class="title function_">create</span>(<span class="number">2</span>) <span class="comment">// ts(2345)</span></span><br><span class="line"><span class="title function_">create</span>(<span class="string">&#x27;string&#x27;</span>) <span class="comment">// ts(2345)</span></span><br></pre></td></tr></table></figure>

<h1 id="类型断言（Type-Assertion）"><a href="#类型断言（Type-Assertion）" class="headerlink" title="类型断言（Type Assertion）"></a>类型断言（Type Assertion）</h1><p>TypeScript 类型检测无法做到绝对智能，毕竟程序不能像人一样思考。有时会碰到我们比 TypeScript 更清楚实际类型的情况，比如下面的例子：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="attr">arrayNumber</span>: <span class="built_in">number</span>[] = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>]</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="attr">greaterThan2</span>: <span class="built_in">number</span> = arrayNumber.<span class="title function_">find</span>(<span class="function">(<span class="params">num</span>) =&gt;</span> num &gt; <span class="number">2</span>) <span class="comment">// 提示 ts(2322)</span></span><br></pre></td></tr></table></figure>

<p>单纯看代码可以看到是有大于 2 的数的，但静态类型对运行时的逻辑无能为力，因为 greaterThan2 有可能是 undefined。</p>
<p>不过，我们可以使用一种笃定的方式——类型断言（类似仅作用在类型层面的强制类型转换）告诉 TypeScript 按照我们的方式做类型检查。比如，我们可以使用 as 语法做类型断言：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="attr">arrayNumber</span>: <span class="built_in">number</span>[] = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>]</span><br><span class="line"><span class="keyword">const</span> <span class="attr">greaterThan2</span>: <span class="built_in">number</span> = arrayNumber.<span class="title function_">find</span>(<span class="function">(<span class="params">num</span>) =&gt;</span> num &gt; <span class="number">2</span>) <span class="keyword">as</span> <span class="built_in">number</span></span><br></pre></td></tr></table></figure>

<p>又或者是使用尖括号 + 类型的格式做类型断言，如下:</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="attr">arrayNumber</span>: <span class="built_in">number</span>[] = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>]</span><br><span class="line"><span class="keyword">const</span> <span class="attr">greaterThan2</span>: <span class="built_in">number</span> = &lt;<span class="built_in">number</span>&gt;arrayNumber.<span class="title function_">find</span>(<span class="function">(<span class="params">num</span>) =&gt;</span> num &gt; <span class="number">2</span>)</span><br></pre></td></tr></table></figure>

<p>以上两种方式虽然没有任何区别，但是尖括号格式会与 JSX 产生语法冲突，因此更推荐使用 as 语法。</p>
<p>另外，any 和 unknown 这两个特殊类型属于万金油，因为它们既可以被断言成任何类型，反过来任何类型也都可以被断言成 any 或 unknown。因此，如果我们想强行“指鹿为马”，就可以先把“鹿”断言为 any 或 unknown，然后再把 any 和 unknown 断言为“马”，比如鹿 as any as 马。</p>
<blockquote>
<p>我们除了可以把特定类型断言成符合约束添加的其他类型之外，还可以使用“字面量值 + as const”语法结构进行常量断言，具体示例如下所示：</p>
</blockquote>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/** str 类型是 &#x27;str&#x27; */</span></span><br><span class="line"><span class="keyword">let</span> str = <span class="string">&#x27;str&#x27;</span> <span class="keyword">as</span> <span class="keyword">const</span></span><br><span class="line"><span class="comment">/** readOnlyArr 类型是 &#x27;readonly [0, 1]&#x27; */</span></span><br><span class="line"><span class="keyword">const</span> readOnlyArr = [<span class="number">0</span>, <span class="number">1</span>] <span class="keyword">as</span> <span class="keyword">const</span></span><br></pre></td></tr></table></figure>

<p>不过断言之后这个 str 就是<code>&#39;str&#39;</code>类型了。</p>
<p>此外还有一种特殊非空断言，即在值（变量、属性）的后边添加 ‘!’ 断言操作符，它可以用来排除值为 null、undefined 的情况，具体示例如下：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="attr">mayNullOrUndefinedOrString</span>: <span class="literal">null</span> | <span class="literal">undefined</span> | <span class="built_in">string</span></span><br><span class="line">mayNullOrUndefinedOrString!.<span class="title function_">toString</span>() <span class="comment">// ok</span></span><br><span class="line">mayNullOrUndefinedOrString.<span class="title function_">toString</span>() <span class="comment">// ts(2531)</span></span><br></pre></td></tr></table></figure>

<blockquote>
<p>对于非空断言来说，我们同样应该把它视作和 any 一样危险的选择。在复杂应用场景中，如果我们使用非空断言，就无法保证之前一定非空的值，比如页面中一定存在 id 为 feedback 的元素，数组中一定有满足 &gt; 2 条件的数字，这些都不会被其他人改变。而一旦保证被改变，错误只会在运行环境中抛出，而静态类型检测是发现不了这些错误的。</p>
</blockquote>
<p>所以，建议使用类型守卫来代替非空断言，比如如下所示的条件判断：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="attr">mayNullOrUndefinedOrString</span>: <span class="literal">null</span> | <span class="literal">undefined</span> | <span class="built_in">string</span></span><br><span class="line"><span class="keyword">if</span> (<span class="keyword">typeof</span> mayNullOrUndefinedOrString === <span class="string">&#x27;string&#x27;</span>) &#123;</span><br><span class="line">  mayNullOrUndefinedOrString.<span class="title function_">toString</span>() <span class="comment">// ok</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h1 id="类型推断"><a href="#类型推断" class="headerlink" title="类型推断"></a>类型推断</h1><p>在 TypeScript 中，类型标注声明是在变量之后（即类型后置），它不像 Java 语言一样，先声明变量的类型，再声明变量的名称。</p>
<p>使用类型标注后置的好处是编译器可以通过代码所在的上下文推导其对应的类型，无须再声明变量类型，具体示例如下：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="keyword">let</span> x1 = <span class="number">42</span> <span class="comment">// 推断出 x1 的类型是 number</span></span><br><span class="line">  <span class="keyword">let</span> <span class="attr">x2</span>: <span class="built_in">number</span> = x1 <span class="comment">// ok</span></span><br><span class="line">  <span class="keyword">let</span> x3 = x2 <span class="comment">// 推断出 x3 的类型是 number</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="上下文推断"><a href="#上下文推断" class="headerlink" title="上下文推断"></a>上下文推断</h2><p>在某些特定的情况下，我们也可以通过变量所在的上下文环境推断变量的类型：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> <span class="title class_">Adder</span> = <span class="function">(<span class="params">a: <span class="built_in">number</span>, b: <span class="built_in">number</span></span>) =&gt;</span> <span class="built_in">number</span></span><br><span class="line"><span class="keyword">const</span> <span class="attr">add</span>: <span class="title class_">Adder</span> = <span class="function">(<span class="params">a, b</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> a + b</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> x1 = <span class="title function_">add</span>(<span class="number">1</span>, <span class="number">1</span>) <span class="comment">// 推断出 x1 类型是 number</span></span><br><span class="line"><span class="keyword">const</span> x2 = <span class="title function_">add</span>(<span class="number">1</span>, <span class="string">&#x27;1&#x27;</span>) <span class="comment">// ts(2345) Argument of type &#x27;&quot;1&quot;&#x27; is not assignable to parameter of type &#x27;number&#x27;</span></span><br></pre></td></tr></table></figure>

<h1 id="字面量类型"><a href="#字面量类型" class="headerlink" title="字面量类型"></a>字面量类型</h1><p>在 TypeScript 中，字面量不仅可以表示值，还可以表示类型，即所谓的字面量类型。</p>
<p>目前，TypeScript 支持 3 种字面量类型：字符串字面量类型、数字字面量类型、布尔字面量类型，对应的字符串字面量、数字字面量、布尔字面量分别拥有与其值一样的字面量类型，如下：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="keyword">let</span> <span class="attr">specifiedStr</span>: <span class="string">&#x27;this is string&#x27;</span> = <span class="string">&#x27;this is string&#x27;</span></span><br><span class="line">  <span class="keyword">let</span> <span class="attr">specifiedNum</span>: <span class="number">1</span> = <span class="number">1</span></span><br><span class="line">  <span class="keyword">let</span> <span class="attr">specifiedBoolean</span>: <span class="literal">true</span> = <span class="literal">true</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>字面量类型是集合类型的子类型，它是集合类型的一种更具体的表达。比如 ‘abc’类型是 string 类型的子类型。数字 1 是数字类型 number 的子类型。</p>
<h2 id="字符串字面量类型"><a href="#字符串字面量类型" class="headerlink" title="字符串字面量类型"></a>字符串字面量类型</h2><p>一般来说，我们可以使用一个字符串字面量类型作为变量的类型，如下所示：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="attr">hello</span>: <span class="string">&#x27;hello&#x27;</span> = <span class="string">&#x27;hello&#x27;</span></span><br><span class="line">hello = <span class="string">&#x27;hi&#x27;</span> <span class="comment">// ts(2322) Type &#x27;&quot;hi&quot;&#x27; is not assignable to type &#x27;&quot;hello&quot;&#x27;</span></span><br></pre></td></tr></table></figure>

<p>实际上，定义单个的字面量类型并没有太大的用处，它真正的应用场景是可以把多个字面量类型组合成一个联合类型，用来描述拥有明确成员的实用的集合，比如：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> <span class="title class_">Direction</span> = <span class="string">&#x27;up&#x27;</span> | <span class="string">&#x27;down&#x27;</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">move</span>(<span class="params">dir: Direction</span>) &#123;</span><br><span class="line">  <span class="comment">// ...</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="title function_">move</span>(<span class="string">&#x27;up&#x27;</span>) <span class="comment">// ok</span></span><br><span class="line"><span class="title function_">move</span>(<span class="string">&#x27;right&#x27;</span>) <span class="comment">// ts(2345) Argument of type &#x27;&quot;right&quot;&#x27; is not assignable to parameter of type &#x27;Direction&#x27;</span></span><br></pre></td></tr></table></figure>

<h2 id="Literal-Widening-字面量类型拓宽"><a href="#Literal-Widening-字面量类型拓宽" class="headerlink" title="Literal Widening &#x2F; 字面量类型拓宽"></a>Literal Widening &#x2F; 字面量类型拓宽</h2><p>所有通过 let 或 var 定义的变量、函数的形参、对象的非只读属性，如果满足指定了初始值且未显式添加类型注解的条件，那么它们推断出来的类型就是指定的初始值字面量类型拓宽后的类型，这就是字面量类型拓宽。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="keyword">let</span> str = <span class="string">&#x27;this is string&#x27;</span> <span class="comment">// 类型是 string</span></span><br><span class="line">  <span class="keyword">let</span> <span class="title function_">strFun</span> = (<span class="params">str = <span class="string">&#x27;this is string&#x27;</span></span>) =&gt; str <span class="comment">// 类型是 (str?: string) =&gt; string;</span></span><br><span class="line">  <span class="keyword">const</span> specifiedStr = <span class="string">&#x27;this is string&#x27;</span> <span class="comment">// 类型是 &#x27;this is string&#x27;</span></span><br><span class="line">  <span class="keyword">let</span> str2 = specifiedStr <span class="comment">// 类型是 &#x27;string&#x27;</span></span><br><span class="line">  <span class="keyword">let</span> <span class="title function_">strFun2</span> = (<span class="params">str = specifiedStr</span>) =&gt; str <span class="comment">// 类型是 (str?: string) =&gt; string;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>基于字面量类型拓宽的条件，我们可以通过如下所示代码添加显示类型注解控制类型拓宽行为。</p>
</blockquote>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="keyword">const</span> <span class="attr">specifiedStr</span>: <span class="string">&#x27;this is string&#x27;</span> = <span class="string">&#x27;this is string&#x27;</span> <span class="comment">// 类型是 &#x27;&quot;this is string&quot;&#x27;</span></span><br><span class="line">  <span class="keyword">let</span> str2 = specifiedStr <span class="comment">// 即便使用 let 定义，类型是 &#x27;this is string&#x27;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="Type-Widening-类型拓宽"><a href="#Type-Widening-类型拓宽" class="headerlink" title="Type Widening &#x2F; 类型拓宽"></a>Type Widening &#x2F; 类型拓宽</h2><p>比如对 null 和 undefined 的类型进行拓宽，通过 let、var 定义的变量如果满足未显式声明类型注解且被赋予了 null 或 undefined 值，则推断出这些变量的类型是 any：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="keyword">let</span> x = <span class="literal">null</span> <span class="comment">// 类型拓宽成 any</span></span><br><span class="line">  <span class="keyword">let</span> y = <span class="literal">undefined</span> <span class="comment">// 类型拓宽成 any</span></span><br><span class="line">  <span class="comment">/** -----分界线------- */</span></span><br><span class="line">  <span class="keyword">const</span> z = <span class="literal">null</span> <span class="comment">// 类型是 null</span></span><br><span class="line">  <span class="comment">/** -----分界线------- */</span></span><br><span class="line">  <span class="keyword">let</span> <span class="title function_">anyFun</span> = (<span class="params">param = <span class="literal">null</span></span>) =&gt; param <span class="comment">// 类型是 (param?: null) =&gt; null</span></span><br><span class="line">  <span class="keyword">let</span> z2 = z <span class="comment">// 类型是 null</span></span><br><span class="line">  <span class="keyword">let</span> x2 = x <span class="comment">// 类型是 null</span></span><br><span class="line">  <span class="keyword">let</span> y2 = y <span class="comment">// 类型是 undefined</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>示例第 7~10 行的类型推断行为因为开启了 strictNullChecks&#x3D;true</p>
</blockquote>
<h2 id="Type-Narrowing-类型缩小"><a href="#Type-Narrowing-类型缩小" class="headerlink" title="Type Narrowing &#x2F; 类型缩小"></a>Type Narrowing &#x2F; 类型缩小</h2><p>在 TypeScript 中，我们可以通过某些操作将变量的类型由一个较为宽泛的集合缩小到相对较小、较明确的集合，这就是 “Type Narrowing”。</p>
<p>比如，我们可以使用类型守卫将函数参数的类型从 any 缩小到明确的类型，具体示例如下：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="keyword">let</span> <span class="title function_">func</span> = (<span class="params">anything: <span class="built_in">any</span></span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> anything === <span class="string">&#x27;string&#x27;</span>) &#123;</span><br><span class="line">      <span class="keyword">return</span> anything <span class="comment">// 类型是 string</span></span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">typeof</span> anything === <span class="string">&#x27;number&#x27;</span>) &#123;</span><br><span class="line">      <span class="keyword">return</span> anything <span class="comment">// 类型是 number</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">null</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>当然，我们也可以通过字面量类型等值判断（&#x3D;&#x3D;&#x3D;）或其他控制流语句（包括但不限于 if、三目运算符、switch 分支）将联合类型收敛为更具体的类型，如下代码所示：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="keyword">type</span> <span class="title class_">Goods</span> = <span class="string">&#x27;pen&#x27;</span> | <span class="string">&#x27;pencil&#x27;</span> | <span class="string">&#x27;ruler&#x27;</span></span><br><span class="line">  <span class="keyword">const</span> <span class="title function_">getPenCost</span> = (<span class="params">item: <span class="string">&#x27;pen&#x27;</span></span>) =&gt; <span class="number">2</span></span><br><span class="line">  <span class="keyword">const</span> <span class="title function_">getPencilCost</span> = (<span class="params">item: <span class="string">&#x27;pencil&#x27;</span></span>) =&gt; <span class="number">4</span></span><br><span class="line">  <span class="keyword">const</span> <span class="title function_">getRulerCost</span> = (<span class="params">item: <span class="string">&#x27;ruler&#x27;</span></span>) =&gt; <span class="number">6</span></span><br><span class="line">  <span class="keyword">const</span> <span class="title function_">getCost</span> = (<span class="params">item: Goods</span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">if</span> (item === <span class="string">&#x27;pen&#x27;</span>) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="title function_">getPenCost</span>(item) <span class="comment">// item =&gt; &#x27;pen&#x27;</span></span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (item === <span class="string">&#x27;pencil&#x27;</span>) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="title function_">getPencilCost</span>(item) <span class="comment">// item =&gt; &#x27;pencil&#x27;</span></span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="title function_">getRulerCost</span>(item) <span class="comment">// item =&gt; &#x27;ruler&#x27;</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#123;</span><br><span class="line">  <span class="keyword">const</span> <span class="title function_">getCost</span> = (<span class="params">item: Goods</span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">if</span> (item === <span class="string">&#x27;pen&#x27;</span>) &#123;</span><br><span class="line">      item <span class="comment">// item =&gt; &#x27;pen&#x27;</span></span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      item <span class="comment">// =&gt; &#x27;pencil&#x27; | &#x27;ruler&#x27;</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

    </div>

    
    
    

    <footer class="post-footer">
          

<div class="post-copyright">
<ul>
  <li class="post-copyright-author">
      <strong>本文作者： </strong>Wyatex
  </li>
  <li class="post-copyright-link">
      <strong>本文链接：</strong>
      <a href="https://wyatex.online/TypeScript/ts%E7%AC%94%E8%AE%B0%EF%BC%881%EF%BC%89%EF%BC%9A%E6%90%AD%E5%BB%BA%E5%92%8C%E4%B8%80%E4%BA%9B%E5%9F%BA%E7%A1%80%E7%B1%BB%E5%9E%8B/" title="ts笔记（1）：搭建和一些基础类型">https://wyatex.online/TypeScript/ts笔记（1）：搭建和一些基础类型/</a>
  </li>
  <li class="post-copyright-license">
      <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" rel="noopener" target="_blank"><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处！
  </li>
</ul>
</div>

          <div class="post-tags">
              <a href="/tags/%E5%89%8D%E7%AB%AF/" rel="tag"># 前端</a>
              <a href="/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/" rel="tag"># 学习笔记</a>
              <a href="/tags/TypeScript/" rel="tag"># TypeScript</a>
          </div>

        

          <div class="post-nav">
            <div class="post-nav-item">
                <a href="/%E6%95%99%E7%A8%8B/%E5%9C%A8%E4%BA%91%E7%AB%AF%E7%BC%96%E7%A8%8B-2-%EF%BC%9ACloudStudio%E8%B0%83%E8%AF%95C%E8%AF%AD%E8%A8%80/" rel="prev" title="在云端编程(2)：CloudStudio调试C语言">
                  <i class="fa fa-angle-left"></i> 在云端编程(2)：CloudStudio调试C语言
                </a>
            </div>
            <div class="post-nav-item">
                <a href="/TypeScript/ts%E7%AC%94%E8%AE%B0%EF%BC%882%EF%BC%89%EF%BC%9A%E5%87%BD%E6%95%B0%E3%80%81%E7%B1%BB%E3%80%81%E6%8E%A5%E5%8F%A3%E7%B1%BB%E5%9E%8B%E5%92%8C%E7%B1%BB%E5%9E%8B%E5%88%AB%E5%90%8D/" rel="next" title="ts笔记（2）：函数、类、接口类型和类型别名">
                  ts笔记（2）：函数、类、接口类型和类型别名 <i class="fa fa-angle-right"></i>
                </a>
            </div>
          </div>
    </footer>
  </article>
</div>






</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">

  <div class="copyright">
    &copy; 2019 – 
    <span itemprop="copyrightYear">2024</span>
    <span class="with-love">
      <i class="fa fa-heart"></i>
    </span>
    <span class="author" itemprop="copyrightHolder">Wyatex</span>
  </div>
<div class="busuanzi-count">
    <span class="post-meta-item" id="busuanzi_container_site_uv">
      <span class="post-meta-item-icon">
        <i class="fa fa-user"></i>
      </span>
      <span class="site-uv" title="总访客量">
        <span id="busuanzi_value_site_uv"></span>
      </span>
    </span>
    <span class="post-meta-item" id="busuanzi_container_site_pv">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="site-pv" title="总访问量">
        <span id="busuanzi_value_site_pv"></span>
      </span>
    </span>
</div>

    </div>
  </footer>

  
  <div class="back-to-top" role="button" aria-label="返回顶部">
    <i class="fa fa-arrow-up fa-lg"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


  
  <script size="300" alpha="0.6" zIndex="-1" src="/lib/ribbon.js/dist/ribbon.min.js"></script>
  <script src="/lib/animejs/lib/anime.min.js" integrity="sha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY=" crossorigin="anonymous"></script>
  <script src="/lib/@next-theme/pjax/pjax.min.js" integrity="sha256-vxLn1tSKWD4dqbMRyv940UYw4sXgMtYcK6reefzZrao=" crossorigin="anonymous"></script>
  <script src="/lib/@fancyapps/ui/dist/fancybox/fancybox.umd.js" integrity="sha256-q8XkJ6dj5VwSvzI8+nATCHHQG+Xv/dAZBCgqmu93zOY=" crossorigin="anonymous"></script>
  <script src="/lib/lozad/dist/lozad.min.js" integrity="sha256-mOFREFhqmHeQbXpK2lp4nA3qooVgACfh88fpJftLBbc=" crossorigin="anonymous"></script>
<script src="/js/comments.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/next-boot.js"></script><script src="/js/pjax.js"></script>

  <script src="/lib/hexo-generator-searchdb/dist/search.js" integrity="sha256-1kfA5uHPf65M5cphT2dvymhkuyHPQp5A53EGZOnOLmc=" crossorigin="anonymous"></script>
<script src="/js/third-party/search/local-search.js"></script>




  <script src="/js/third-party/fancybox.js"></script>



  
  <script data-pjax async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>





</body>
</html>
